using System;
using System.Web.Services;
using System.Collections.Generic;
using System.Web.Services.Protocols;

namespace IFXplus.SmartStorage.Providers
{
    
    [WebService]
    public abstract class WebServiceStorageProviderBase : WebService    
    {
        [WebMethod]
        protected abstract List<StorageProviderReference> GetProviders();

        [WebMethod]
        [WebServiceStorageProviderClientCredentialsExtension]
        [SoapHeader("Credentials")]
        public void Insert(StorageEntry value)
        {
            foreach (StorageProviderReference spr in GetProviders())
                StorageProviderFactory.GetStorageProvider(spr).Insert(value);
        }

        [WebMethod]
        [WebServiceStorageProviderClientCredentialsExtension]
        [SoapHeader("Credentials")]
        public void Remove(string key)
        {
            foreach (StorageProviderReference spr in GetProviders())
                StorageProviderFactory.GetStorageProvider(spr).Remove(key);
        }

        [WebMethod]
        [WebServiceStorageProviderClientCredentialsExtension]
        [SoapHeader("Credentials")]
        public StorageEntry Get(string key)
        {
            foreach (StorageProviderReference spr in GetProviders())
            {
                StorageEntry entry = StorageProviderFactory.GetStorageProvider(spr).Get(key);
                if (entry != null)
                    return entry;
            }
            return null;
        }

        #region WebService Security

        protected abstract string Username { get; }
        protected abstract string Password { get; }

        public WebServiceStorageProviderClientCredentials Credentials;

        #region WebServiceStorageProviderClientCredentialsExtensionAttribute

        [AttributeUsage(AttributeTargets.Method)]
        public class WebServiceStorageProviderClientCredentialsExtensionAttribute : SoapExtensionAttribute
        {
            int _priority = 1;

            public override int Priority
            {
                get { return _priority; }
                set { _priority = value; }
            }

            public override Type ExtensionType
            {
                get { return typeof(WebServiceStorageProviderClientCredentialsExtension); }
            }
        }

        #endregion

        #region WebServiceStorageProviderClientCredentialsExtension

        public class WebServiceStorageProviderClientCredentialsExtension : SoapExtension
        {
            public override void ProcessMessage(SoapMessage message)
            {
                if (message.Stage == SoapMessageStage.AfterDeserialize)
                {
                    string username, password;
                    try
                    {
                        WebServiceStorageProviderBase server = (WebServiceStorageProviderBase)((SoapServerMessage) message).Server;
                        username = server.Username;
                        password = server.Password;
                    }
                    catch
                    {
                        return;
                    }
                    // check credentials in SOAP headers:
                    foreach (SoapHeader header in message.Headers)
                    {
                        if (header is WebServiceStorageProviderClientCredentials)
                        {
                            WebServiceStorageProviderClientCredentials credentials = (WebServiceStorageProviderClientCredentials)header;
                            if (credentials.Username == username && credentials.Password == password)
                                return;
                            break;
                        }
                    }
                    // credentials not founded or invalid:
                    throw new SoapException("Unauthorized", SoapException.ClientFaultCode);
                }
            }

            public override object GetInitializer(Type type)
            {
                return GetType();
            }

            public override object GetInitializer(LogicalMethodInfo info, SoapExtensionAttribute attribute)
            {
                return null;
            }

            public override void Initialize(object initializer) { }
        }

        #endregion

        #endregion
    }
}
